/** \file    io.h
  * \brief   images input/output.
  * \date    2002, 2003
  * \author  Fedor Chelnokov
  * \version $Header: /home/cscom1r4/cvsroot/cs/include/imglib/io.h,v 1.2 2004/04/30 19:13:30 cscom1r4 Exp $
  */

#ifndef _io_h_
#define _io_h_

#include "imageclass_decl.h"
#include "io_error.h"
#include "io_types.h"

namespace img {

class ext_provider
{
public:
	virtual ~ext_provider() {}
	///list of extensions
	virtual void formats(ext_vec & f) const = 0;
	///semicolon separated search list, e.g. "*.gif;*.bmp"
	virtual std::string search_str() const;
};

inline std::string ext_provider::search_str() const
{
	ext_vec f;
	formats(f);
	return f.search_str();
}

///abstract image reader interface
class reader : public ext_provider
{
public:
	virtual ~reader() {}
	///return true if image is readable
	virtual bool ping(const std::string & path, file_info * info = 0) const = 0;
	virtual bool ping(const std::string & path, const std::string & format, file_info * info = 0) const = 0;
	///return true if ping is significantly faster then read (at least without getting info)
	virtual bool fast_ping() const = 0;
	virtual void read(const std::string & path, byte_image & img) const = 0;
	virtual void read(const std::string & path, const std::string & format, byte_image & img) const = 0;
};

///abstract image writer interface
class writer : public ext_provider
{
public:
	virtual ~writer() {}
	///return size of image written
	virtual size_t write(const std::string & path, const std::string & format, const byte_image & img, bool alpha = false) = 0;
	///automatically determine format from extension
	size_t write_autoformat(const std::string & path, const byte_image & img, bool alpha = false);
};

///////////////////////////////////////////////
// read/write using multiple readers/writers //
///////////////////////////////////////////////

class multireader : public reader
{
	std::vector<reader*> _readers;
public:
	///adapted readers will be called in the order of insertion
	///reader r will be deleted in ~multireader()
	void insert(reader * r);

public:
	virtual ~multireader();
	virtual bool ping(const std::string & path, file_info * info = 0) const;
	virtual bool ping(const std::string & path, const std::string & format, file_info * info = 0) const;
	virtual bool fast_ping() const;
	virtual void read(const std::string & path, byte_image & img) const;
	virtual void read(const std::string & path, const std::string & format, byte_image & img) const;
	virtual void formats(ext_vec & f) const;
};

struct our_qt_im_multireader : multireader
	{ our_qt_im_multireader(); };

struct our_im_multireader : multireader
	{ our_im_multireader(); };

struct our_gdiplus_multireader : multireader
	{ our_gdiplus_multireader(); };

class multiwriter : public writer
{
	std::vector<writer*> _writers;
public:
	///adapted writers will be called in the order of insertion
	///writer w will be deleted in ~multiwriter()
	void insert(writer * w);

public:
	virtual ~multiwriter();
	virtual size_t write(const std::string & path, const std::string & format, const byte_image & img, bool alpha = false);
	virtual void formats(ext_vec & f) const;
};

struct our_qt_im_multiwriter : multiwriter
	{ our_qt_im_multiwriter(); };

struct our_im_multiwriter : multiwriter
	{ our_im_multiwriter(); };

struct our_gdiplus_multiwriter : multiwriter
	{ our_gdiplus_multiwriter(); };

////////////////////
// our read/write // 
////////////////////

// We believe they are the fastest

class our_reader : public reader
{
public:
	virtual bool ping(const std::string & path, file_info * info = 0) const;
	virtual bool ping(const std::string & path, const std::string & format, file_info * info = 0) const;
	virtual bool fast_ping() const;
	virtual void read(const std::string & path, byte_image & img) const;
	virtual void read(const std::string & path, const std::string & format, byte_image & img) const;
	virtual void formats(ext_vec & f) const;
	virtual std::string search_str() const;
};

class our_writer : public writer
{
public:
	virtual size_t write(const std::string & path, const std::string & format, const byte_image & img, bool alpha = false);
	virtual void formats(ext_vec & f) const;
	virtual std::string search_str() const;
};

/////////////////////
// GDI+ read/write // 
/////////////////////

class gdiplus_reader : public reader
{
public:
	virtual bool ping(const std::string & path, file_info * info = 0) const;
	virtual bool ping(const std::string & path, const std::string & format, file_info * info = 0) const;
	virtual bool fast_ping() const;
	virtual void read(const std::string & path, byte_image & img) const;
	virtual void read(const std::string & path, const std::string & format, byte_image & img) const;
	virtual void formats(ext_vec & f) const;
	virtual std::string search_str() const;
};

class gdiplus_writer : public writer
{
public:
	virtual size_t write(const std::string & path, const std::string & format, const byte_image & img, bool alpha = false);
	virtual void formats(ext_vec & f) const;
	virtual std::string search_str() const;
};

///////////////////
// Qt read/write //
///////////////////

class qt_reader : public reader
{
public:
	virtual bool ping(const std::string & path, file_info * info = 0) const;
	virtual bool ping(const std::string & path, const std::string & format, file_info * info = 0) const;
	virtual bool fast_ping() const;
	virtual void read(const std::string & path, byte_image & img) const;
	virtual void read(const std::string & path, const std::string & format, byte_image & img) const;
	virtual void formats(ext_vec & f) const;
};

class qt_writer : public writer
{
public:
	virtual size_t write(const std::string & path, const std::string & format, const byte_image & img, bool alpha = false);
	virtual void formats(ext_vec & f) const;
};

////////////////////////////
// ImageMagick read/write //
////////////////////////////

class magick_reader : public reader
{
public:
	virtual bool ping(const std::string & path, file_info * info = 0) const;
	virtual bool ping(const std::string & path, const std::string & format, file_info * info = 0) const;
	virtual bool fast_ping() const;
	virtual void read(const std::string & path, byte_image & img) const;
	virtual void read(const std::string & path, const std::string & format, byte_image & img) const;
	virtual void formats(ext_vec & f) const;
};

class magick_writer : public writer
{
public:
	virtual size_t write(const std::string & path, const std::string & format, const byte_image & img, bool alpha = false);
	virtual void formats(ext_vec & f) const;
};

} //namespace img

#endif //_io_h_
